/*
 * The JAnalytics Library provides a Java API to the Google Analytics service.
 * Copyright (C) 2007 Ansir Development Limited (http://www.ansir.ca)
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

package ca.ansir.analytics.tag;

import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Calendar;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
import javax.xml.transform.TransformerException;

import ca.ansir.analytics.reports.FilterModes;
import ca.ansir.analytics.reports.JAnalytics;
import ca.ansir.analytics.reports.JAnalyticsException;
import ca.ansir.analytics.reports.ReportTypes;
import ca.ansir.analytics.transform.TemplateTransform;
import ca.ansir.analytics.util.Utilities;

/**
 * The <code>KMLTag</code> class is used to retrieve the Geo Map Overlay XML
 * report and transform and write out a corresponding KML. This tag is bound to
 * the example web application via the Tag Library Definition (janalytics.tld)
 * located in the example/WEB-INF directory.
 * 
 * @author Dan Andrews
 */
public class KMLTag extends TagSupport {

	/** Generated serialVersionUID */
	private static final long serialVersionUID = 2683950890772288454L;

	/** Filter mode "match" value. */
	private static final String MATCH = "match";

	/** Filter mode "dont" match value. */
	private static final String DONT_MATCH = "dont";

	/** Location of the kml.xsl resource */
	private static final String KML_XSL_LOCATION = "ca/ansir/analytics/xsl/kml.xsl";

	/** The default number of days to retrieve (today and yesterday). */
	private static final int DEFAULT_DAYS = 2;

	/** The email (required). */
	private String email;

	/** The password (required). */
	private String password;

	/** The report id (optional). */
	private String reportid;

	/** The filter (optional default is ""). */
	private String filter;

	/** The filter mode (optional default is "dont"). */
	private String filtermode;

	/** The limit (optional default is JAnalytics.DEFAULT_MAX_LIMIT). */
	private int limit;

	/** The filter mode (optional default is 2). */
	private int days;

	/**
	 * Constructor.
	 */
	public KMLTag() {
		init();
	}

	/**
	 * Initialize and re-initialize.
	 */
	private void init() {
		email = null;
		password = null;
		reportid = null;
		// limit = JAnalytics.DEFAULT_MAX_LIMIT;
		limit = 1000;
		filter = "";
		filtermode = DONT_MATCH;
		days = DEFAULT_DAYS;
	}

	/**
	 * Process the start of the tag.
	 * 
	 * @return The SKIP_BODY constant.
	 */
	public int doStartTag() {
		return Tag.SKIP_BODY;
	}

	/**
	 * Process the end of the tag.
	 * 
	 * @return The SKIP_BODY constant.
	 */
	public int doEndTag() throws JspException {
		writeTag(pageContext.getOut());
		init();
		return Tag.SKIP_BODY;
	}

	/**
	 * Writes the out the KML.
	 * 
	 * @param writer
	 *            The JspWriter to write to.
	 * @throws JspException
	 */
	private void writeTag(Writer writer) throws JspException {
		// JAnalytics analytics = new JAnalytics();
		try {
			// analytics.login(email, password);
			// if (reportid == null) {
			// reportid = analytics.getReportIds()[0];
			// }
			Calendar startTime = Calendar.getInstance();
			if (days > 1) {
				Utilities.rollCalendarDay(startTime, -1 * (days - 1));
			}
			Calendar endTime = Calendar.getInstance();
			FilterModes filterMode = FilterModes.fromInt(filtermode
					.equals(DONT_MATCH) ? FilterModes._DONT_MATCH
					: FilterModes._MATCH);

			// Utilities will automatically use cache if configured
			InputStream inXML = Utilities.getDocumentAsInputStream(email,
					password, reportid, ReportTypes.GEO_MAP_DETAIL_CITY_REPORT, startTime,
					endTime, filter, filterMode, limit);

			InputStream inXSL = TemplateTransform.class.getClassLoader()
					.getResourceAsStream(KML_XSL_LOCATION);

			TemplateTransform.applyTransform(inXML, inXSL, writer);
		} catch (JAnalyticsException e) {
			throw new JspException(e.getMessage(), e);
		} catch (TransformerException e) {
			throw new JspException(e.getMessage(), e);
		}
	}

	/**
	 * Gets the days.
	 * 
	 * @return The days.
	 */
	public int getDays() {
		return days;
	}

	/**
	 * Sets the days.
	 * 
	 * @param days
	 *            The days to set.
	 */
	public void setDays(int days) {
		if (days < 1) {
			throw new IllegalArgumentException(
					"Days must be greater than zero.");
		}
		this.days = days;
	}

	/**
	 * Gets the email.
	 * 
	 * @return The email.
	 */
	public String getEmail() {
		return email;
	}

	/**
	 * Sets the email.
	 * 
	 * @param email
	 *            The email to set.
	 */
	public void setEmail(String email) {
		if ("".equals(email.trim()) || email == null) {
			throw new IllegalArgumentException("Email must not be empty.");
		}
		this.email = email;
	}

	/**
	 * Gets the filter.
	 * 
	 * @return The filter.
	 */
	public String getFilter() {
		return filter;
	}

	/**
	 * Sets the filter.
	 * 
	 * @param filter
	 *            The filter to set.
	 */
	public void setFilter(String filter) {
		this.filter = filter;
	}

	/**
	 * Gets the filter mode.
	 * 
	 * @return The filtermode.
	 */
	public String getFiltermode() {
		return filtermode;
	}

	/**
	 * Sets the filter mode.
	 * 
	 * @param filtermode
	 *            The filtermode to set.
	 */
	public void setFiltermode(String filtermode) {
		if (!filtermode.equalsIgnoreCase(DONT_MATCH)
				|| !filtermode.equalsIgnoreCase(MATCH)) {
			throw new IllegalArgumentException("Filter mode must be '"
					+ DONT_MATCH + "' or '" + DONT_MATCH + "'.");
		}
		this.filtermode = filtermode.toLowerCase();
	}

	/**
	 * Gets the limit.
	 * 
	 * @return The limit.
	 */
	public int getLimit() {
		return limit;
	}

	/**
	 * Sets the limit.
	 * 
	 * @param limit
	 *            The limit to set.
	 */
	public void setLimit(int limit) {
		if (limit > 1000 || limit < 0) {
			throw new IllegalArgumentException(
					"Limit must be greater than zero and "
							+ "less than or equal to "
							+ 1000 + ".");
		}
		this.limit = limit;
	}

	/**
	 * Gets the password.
	 * 
	 * @return The password.
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * Sets the password.
	 * 
	 * @param password
	 *            The password to set.
	 */
	public void setPassword(String password) {
		if ("".equals(password.trim()) || password == null) {
			throw new IllegalArgumentException("Password must not be empty.");
		}
		this.password = password;
	}

	/**
	 * Gets the report id.
	 * 
	 * @return The reportid.
	 */
	public String getReportid() {
		return reportid;
	}

	/**
	 * Sets the report id.
	 * 
	 * @param reportid
	 *            The reportid to set.
	 */
	public void setReportid(String reportid) {
		this.reportid = reportid;
	}

	/**
	 * Standalone test.
	 * 
	 * @param args
	 *            email passwords
	 */
	public static void main(String[] args) throws Exception {
		KMLTag tag = new KMLTag();
		tag.setEmail(args[0]);
		tag.setPassword(args[1]);
		tag.setDays(3);

		ca.ansir.analytics.cache.DocumentCacheFactory
				.loadConfig((new java.io.File(
						"C:/nbprojects/JAnalytics/web/WEB-INF/analylics.xml")
						.toURL()));

		Writer w = new PrintWriter(System.out);
		try {
			tag.writeTag(w);
		} catch (JspException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
